From 08d9a57c6e1022143c747799dd10043a7275a196 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 15 Oct 2019 04:18:10 +0200 Subject: [PATCH] listitem: Change focus handling Focus in the listitem now works like this: 1. If any child can take focus, do not ever attempt to take focus. 2. Otherwise, if this item is selectable or activatable, allow focusing this widget. This makes sure every item in a list is focusable for activation and selection handling, but no useless widgets get focused and moving focus is as fast as possible. --- gtk/gtklistitem.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/gtk/gtklistitem.c b/gtk/gtklistitem.c index 842f04b70d..08e866f908 100644 --- a/gtk/gtklistitem.c +++ b/gtk/gtklistitem.c @@ -86,6 +86,51 @@ G_DEFINE_TYPE (GtkListItem, gtk_list_item, GTK_TYPE_WIDGET) static GParamSpec *properties[N_PROPS] = { NULL, }; +static gboolean +gtk_list_item_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + GtkListItem *self = GTK_LIST_ITEM (widget); + + /* The idea of this function is the following: + * 1. If any child can take focus, do not ever attempt + * to take focus. + * 2. Otherwise, if this item is selectable or activatable, + * allow focusing this widget. + * + * This makes sure every item in a list is focusable for + * activation and selection handling, but no useless widgets + * get focused and moving focus is as fast as possible. + */ + if (self->child) + { + if (gtk_widget_get_focus_child (widget)) + return FALSE; + if (gtk_widget_child_focus (self->child, direction)) + return TRUE; + } + + if (gtk_widget_is_focus (widget)) + return FALSE; + + if (!gtk_widget_get_can_focus (widget) || + !self->selectable) + return FALSE; + + return gtk_widget_grab_focus (widget); +} + +static gboolean +gtk_list_item_grab_focus (GtkWidget *widget) +{ + GtkListItem *self = GTK_LIST_ITEM (widget); + + if (self->child && gtk_widget_grab_focus (self->child)) + return TRUE; + + return GTK_WIDGET_CLASS (gtk_list_item_parent_class)->grab_focus (widget); +} + static void gtk_list_item_dispose (GObject *object) { @@ -163,6 +208,9 @@ gtk_list_item_class_init (GtkListItemClass *klass) GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + widget_class->focus = gtk_list_item_focus; + widget_class->grab_focus = gtk_list_item_grab_focus; + gobject_class->dispose = gtk_list_item_dispose; gobject_class->get_property = gtk_list_item_get_property; gobject_class->set_property = gtk_list_item_set_property; @@ -542,7 +590,5 @@ gtk_list_item_set_selectable (GtkListItem *self, self->selectable = selectable; - gtk_widget_set_can_focus (GTK_WIDGET (self), self->selectable); - g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SELECTABLE]); } -- 2.30.2